﻿// =====================================================================
//
//  This file is part of the Microsoft Dynamics CRM SDK code samples.
//
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
//
//  THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//
// =====================================================================
#region

using System;
using System.Collections.Generic;
using System.Security;
using Microsoft.Xrm.Sdk.Client.Protocols.Policy;


#endregion

namespace Microsoft.Xrm.Sdk.Client
{
	internal static class LiveIdAuthenticationConfiguration
	{
		internal static String DeviceTokenId = "urn:liveid:device";
		internal static String UserNameTokenId = "user";
		internal static String DeviceUserNameTokenId = "devicesoftware";
		internal static String PolicyReference = "http://schemas.xmlsoap.org/ws/2004/09/policy";

		internal static String SecurityTokenSchema =
			"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
		internal static String DefaultPolicy = "MBI_FED_SSL";
	}

	public sealed class PolicyDictionary : Dictionary<String, String>
	{
	}


	internal static class PolicyHelper
	{

		internal static String GetPolicyValue(AuthenticationPolicy xrmPolicy, String elementName, String defaultValue)
		{
			if (xrmPolicy != null)
			{
				String elementValue;

				if (xrmPolicy.PolicyElements.TryGetValue(elementName, out elementValue))
				{
					return elementValue;
				}
			}
			return defaultValue;
		}
	}

	public abstract class PolicyConfiguration
	{
		internal PolicyConfiguration(ServiceEndpointMetadata serviceEndpointMetadata)
		{
			ServiceEndpointMetadata = serviceEndpointMetadata;
			Initialize();
		}

		public ServiceEndpointMetadata ServiceEndpointMetadata { get; private set; }

		public String SecureTokenServiceIdentifier { get; private set; }

		public String SecureTokenServiceTrustEndpoint { get; private set; }

		private void Initialize()
		{
			SecureTokenServiceIdentifier = GetPolicyValue(ServiceEndpointMetadata.AuthenticationPolicy,
														  AuthPolicyConstants.SecureTokenServiceIdentifier, String.Empty);
			SecureTokenServiceTrustEndpoint = GetPolicyValue(ServiceEndpointMetadata.TokenPolicy,
															 "SecureTokenServiceTrustEndpoint", String.Empty);
		}

		internal String GetPolicyValue(ServicePolicy servicePolicy, String elementName, String defaultValue)
		{
			if (servicePolicy != null)
			{
				String elementValue;

				if (servicePolicy.PolicyElements.TryGetValue(elementName, out elementValue))
				{
					return elementValue;
				}
			}
			return defaultValue;
		}
	}

	public sealed class WindowsPolicyConfiguration : PolicyConfiguration
	{
		internal WindowsPolicyConfiguration(ServiceEndpointMetadata serviceEndpointMetadata)
			: base(serviceEndpointMetadata)
		{
		}
	}

	public sealed class ClaimsPolicyConfiguration : PolicyConfiguration
	{
		internal ClaimsPolicyConfiguration(ServiceEndpointMetadata serviceEndpointMetadata)
			: base(serviceEndpointMetadata)
		{
		}
	}

	public abstract class OnlinePolicyConfiguration : PolicyConfiguration
	{
		internal OnlinePolicyConfiguration(ServiceEndpointMetadata serviceEndpointMetadata)
			: base(serviceEndpointMetadata)
		{
			Policy = GetPolicyValue(ServiceEndpointMetadata.AuthenticationPolicy, AuthPolicyConstants.LiveTrustLivePolicy, "MBI_FED_SSL");
			LiveIdAppliesTo = GetPolicyValue(ServiceEndpointMetadata.AuthenticationPolicy, AuthPolicyConstants.LiveIdAppliesTo,
											 @"http://Passport.NET/tb");
		}

		public string Policy { get; set; }

		public string LiveIdAppliesTo { get; set; }

		public string AppliesTo { get; set; }


		private IdentityProviderTypeDictionary _onlineProviders = new IdentityProviderTypeDictionary();
		public IdentityProviderTypeDictionary OnlineProviders { get { return _onlineProviders; } }

	}

	public sealed class LiveIdPolicyConfiguration : OnlinePolicyConfiguration
	{
		internal LiveIdPolicyConfiguration(ServiceEndpointMetadata serviceEndpointMetadata)
			: base(serviceEndpointMetadata)
		{
			var liveTrustEndpoint = new LiveIdentityProviderTrustConfiguration(serviceEndpointMetadata.AuthenticationPolicy);
			AppliesTo = GetPolicyValue(ServiceEndpointMetadata.AuthenticationPolicy, AuthPolicyConstants.AppliesTo, "");
		}
	}

	/// <summary>
	/// Used to manage the LiveFederation configuration.  In this configuration, we will have a true STS, but must be able to talk to 
	/// MFG for initial authentication when not using HomeRealmUrl.
	/// </summary>
	[SecuritySafeCritical()]
	public sealed class OnlineFederationPolicyConfiguration : OnlinePolicyConfiguration
	{
		internal OnlineFederationPolicyConfiguration(ServiceEndpointMetadata metadata)
			: base(metadata)
		{
			var xrmPolicy = metadata.AuthenticationPolicy;
			if (!String.IsNullOrEmpty(PolicyHelper.GetPolicyValue(xrmPolicy, AuthPolicyConstants.LiveTrustLivePolicy, String.Empty)))
			{
				var liveTrustEndpoint = new LiveIdentityProviderTrustConfiguration(xrmPolicy);
				OnlineProviders.Add(liveTrustEndpoint.Endpoint.GetServiceRoot(), liveTrustEndpoint);
			}
			if (!String.IsNullOrEmpty(PolicyHelper.GetPolicyValue(xrmPolicy, AuthPolicyConstants.OrgIdPolicy, String.Empty)))
			{
				var orgTrustEndpoint = new OrgIdentityProviderTrustConfiguration(xrmPolicy);
				OnlineProviders.Add(orgTrustEndpoint.Endpoint.GetServiceRoot(), orgTrustEndpoint);
			}
		}
	}
}
